﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Broker.Service.EntityModel;
using BrokerBase.Lib.Client;
using BrokerBase.Lib.Tool;
using System.Data;

namespace Broker.Service.Model
{
    public class ActiveCodeUtil
    {

        public const int DEFAULT_INVITED_CODE_QTY = 10;
        private const int SERIAL_MAX_LENGTH = 25;
        private static readonly char[] Seeds = new char[31] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', '2', '3', '4', '5', '6', '7', '8', '9' };

        public static Sale_ActiveCode GetActiveCodeByVerify(string activeCode, RegistrantInfo registrantInfo, TerminalInfo terminalInfo,broker30Entities entity,IDbTransaction tx, out string message)
        {

            try
            {

                if (string.IsNullOrEmpty(activeCode))
                {
                    message = "激活码不能为空";
                    return null;
                }

                if (terminalInfo == null)
                {
                    message = "客户端信息错误";
                    return null;
                }

                if (string.IsNullOrEmpty(registrantInfo.UserName))
                {
                    message = "注册名不能为空";
                    return null;
                }

                if (registrantInfo.PresenterName == registrantInfo.UserName)
                {
                    message = "推荐不能是自己";
                    return null;
                }

                if (!string.IsNullOrEmpty(registrantInfo.PresenterName) && !ClientUtil.IsNameExist(registrantInfo.PresenterName,entity))
                {

                    message = "推荐人不存在";
                    return null;
                }

                Sale_ActiveCode sac = entity.Sale_ActiveCode.FirstOrDefault(p => p.Code == activeCode);

                if (sac == null)
                {
                    message = "序列号不存在";
                    return null;
                }

                Sale_Client sclient = entity.Sale_Client.FirstOrDefault(p => p.Name == registrantInfo.UserName);


                if (sclient == null)
                {
                    if (sac.IsRenewal)
                    {
                        message = "要续费的注册名不存在";
                        return null;
                    }

                    if (sac.RegTime != null)//新用户不可能使用已存在的激活码!
                    {
                        message = "激活码已经被使用过";
                        return null;
                    }
                }
                else
                {

                    if (sac.RegTime == null)//激活码还没有注册过
                    {
                        bool isTrial = ClientUtil.IsTrial(sclient,entity);
                        //假如不是试用用户，并且激活码不是续费
                        if (!isTrial && !sac.IsRenewal)
                        {
                            message = "已存在的注册用户只能使用续费类型的激活码" + Environment.NewLine + "如果是新建用户请检查用户名是否存在";
                            return null;
                        }

                        if (isTrial && sac.IsRenewal)
                        {
                            message = "试用注册用户不能使用续费类型的激活码";
                            return null;
                        }
                    }
                    else//用户名存在并且已经激活，首先判断用户名是否匹配，再判断机器硬件是否匹配
                    {

                        Sale_ActiveCode tmpAc = entity.Sale_ActiveCode.FirstOrDefault(p => p.Id == sac.Id && p.RegistrantId == sclient.Id);

                        if (tmpAc == null)
                        {
                            message = "用户名与激活码不匹配";
                            return null;
                        }
                        else
                        {

                            int lasRegId = entity.Sale_ActiveCodeReg.Where(p => p.ActiveCodeId == sac.Id).Max(q => q.Id);

                            Sale_ActiveCodeReg reg = entity.Sale_ActiveCodeReg.FirstOrDefault(p => p.Id == lasRegId);

                            if (reg.DISKSerialNo != terminalInfo.DISKSerialNo && reg.MACSerialNo != terminalInfo.MACSerialNo && reg.MBSerialNo != terminalInfo.MBSerialNo)
                            {
                                message = "激活码已经被使用过";
                                return null;
                            }

                        }
                    }
                }

                //激活码第一次注册，并且注册时间是否已经超出有效注册期
                if (sac.RegTime == null && DateTimeUtil.ChinaStandardTime > sac.SendTime.Value.AddDays(sac.RegPeriod))
                {
                    message = "激活码注册时间已经过期!";
                    return null;
                }

                //Client user = ac.Client;


                if (sac.RegistrantId != null)//续费的用户名必须匹配!
                {
                    Sale_Client c = entity.Sale_Client.FirstOrDefault(p => p.Id == sac.RegistrantId);

                    if (c != null && c.Name != registrantInfo.UserName)
                    {
                        message = "激活码与注册名不匹配";
                        return null;
                    }
                }

                //假如是试用码，不允许在多台机器上注册！
                if (sac.Edition == (int)EditionType.Evaluation)
                {
                    Sale_ActiveCodeReg reg = null;
                    if (sac.RegTime != null)
                    {
                        reg = entity.Sale_ActiveCodeReg.FirstOrDefault(p => p.DISKSerialNo == terminalInfo.DISKSerialNo || p.MBSerialNo == terminalInfo.MBSerialNo || p.MACSerialNo == terminalInfo.MACSerialNo);

                        if (reg == null)
                        {
                            message = "该注册码已经注册过!";
                            return null;
                        }
                    }
                    else
                    {

                        var q = from a in entity.Sale_ActiveCode
                                join r in entity.Sale_ActiveCodeReg on a.Id equals r.ActiveCodeId
                                where a.RegistrantId == sclient.Id &&
                                    a.Edition == (int)EditionType.Evaluation &&
                                    a.Code != activeCode &&
                                    r.DISKSerialNo == terminalInfo.DISKSerialNo &&
                                    r.MACSerialNo == terminalInfo.MACSerialNo &&
                                    r.MBSerialNo == terminalInfo.MBSerialNo
                                select a;

                        if (q.Count() > 0)
                        {
                            message = "一台电脑只能使用一个试用码";
                            return null;
                        }

                    }


                }
                message = null;
                return sac;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public static Sale_ActiveCodeReg Register(Sale_ActiveCode code, RegistrantInfo registrantInfo, TerminalInfo terminalInfo, string ipAddress, broker30Entities entity, IDbTransaction tx, out string Message)
        {
            try
            {

                Sale_Client client = null;
                Sale_Client presenter = null;

                bool isNewUser = false;

                DateTime currentTime = DateTimeUtil.ChinaStandardTime;

                if (entity.Sale_Client.FirstOrDefault(p => p.Name == registrantInfo.UserName) == null)
                {
                    client = new Sale_Client();
                    client.Name = registrantInfo.UserName;
                    client.Leaf = true;
                    client.LicenseCode = Guid.NewGuid().ToString();
                    client.CreateDate = currentTime;
                    client.InviteCodeQty = DEFAULT_INVITED_CODE_QTY;
                    client.TotalAmount = 0;
                    client.TotalScore = 0;

                    if (!string.IsNullOrEmpty(registrantInfo.PresenterName))
                    {
                        presenter = entity.Sale_Client.FirstOrDefault(p => p.Name == registrantInfo.PresenterName);

                        if (presenter != null)
                        {
                            client.ParentId = presenter.Id;
                            presenter.Leaf = false;


                        }
                    }

                    client.FLevel = presenter == null ? 1 : presenter.FLevel + 1;
                    client.RegTime = client.CreateDate;

                    entity.Sale_Client.AddObject(client);
                    entity.SaveChanges();

                    isNewUser = true;
                }
                else
                {
                    client = entity.Sale_Client.FirstOrDefault(p => p.Name == registrantInfo.UserName);
                }

                client.PolicyId = code.PolicyId;
                client.LastRegTime = currentTime;

                if (code.RegTime == null)//还没有注册过
                {
                    code.RegistrantId = client.Id;
                    //entity.SaveChanges();

                    if (isNewUser)
                    {
                        code.BeginTime = new DateTime(currentTime.Year, currentTime.Month, currentTime.Day);//只取年-月-日
                    }
                    else
                    {
                        DateTime? maxEndTime = entity.Sale_ActiveCode.Where(p => p.RegistrantId == client.Id).Max(q => q.EndTime);//找到该用户激活码最大的有效期结束时间
                        //DateTime? maxEndTime = client.ActiveCodes.Max(p => p.EndTime);//找到该用户激活码最大的有效期结束时间

                        if (currentTime > maxEndTime)//假如当前时间已经大于用户最大的有效期结束时间(表明客户中间有个间断期)
                        {
                            code.BeginTime = new DateTime(currentTime.Year, currentTime.Month, currentTime.Day);//只取年-月-日
                        }
                        else
                        {
                            code.BeginTime = maxEndTime.Value.AddDays(1);//最大日期加一条
                        }
                    }
                    code.EndTime = code.BeginTime.Value.AddMonths(code.Period);
                    //code.LicenseCode = client.LicenseCode;//如果是第一次激活，激活码序列号等于客户对应的产品序列号
                    client.TotalAmount += code.Amount;    //更新累计金额
                }

                client.FullPath = presenter == null ? client.Id.ToString() : presenter.FullPath + "." + client.Id;

                Sale_ActiveCodeReg reg = new Sale_ActiveCodeReg();
                reg.ActiveCodeId = code.Id;
                reg.RegTime = currentTime;
                reg.DISKSerialNo = terminalInfo.DISKSerialNo;
                reg.MACSerialNo = terminalInfo.MACSerialNo;
                reg.OSVersion = terminalInfo.OSVersion;
                reg.RegIPAddress = ipAddress;
                reg.MBSerialNo = terminalInfo.MBSerialNo;

                entity.Sale_ActiveCodeReg.AddObject(reg);
                entity.SaveChanges();

                //更新所有(最大32层)推荐人的积分记录,只有不是续费类型，并且第一次激活时才更新积分，重复激活不更新积分！
                if (!code.IsRenewal && code.RegTime == null)
                {
                    UpdateScore(client, presenter, code, reg, entity, tx);
                }

                code.RegTime = currentTime;//激活码最后注册时间

                entity.SaveChanges();//更新数据

                Message = null;
                return reg;

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }


        public static void UpdateScore(Sale_Client provider,Sale_Client presenter,Sale_ActiveCode code, Sale_ActiveCodeReg reg, broker30Entities entity,IDbTransaction tx)
        {

            Sale_Client client = presenter;

            Score_ScoreRecordType socRecType = entity.Score_ScoreRecordType.FirstOrDefault(p => p.TypeStyle == 1);

            int i = 0;

            while (client != null && i <= ScoreRuleUtil.INTERNAL_MAX_LEVEL)
            {
                i++;

                if (!ClientUtil.IsTrial(client,entity) && client.PolicyId != null)
                {
                    Score_Rule scoreRule=(from rule in entity.Score_Rule 
                                            join policy in entity.Score_Policy on rule.PolicyId equals policy.Id
                                            join c in entity.Sale_Client on policy.Id equals c.PolicyId
                                            where c.Id==client.Id && rule.Edition==code.Edition
                                            select rule).FirstOrDefault();

                    if((scoreRule !=null && i<scoreRule.MaxLevel) || scoreRule==null)
                    {
                        Score_ScoreRecord record=ClientUtil.CreateOrUpdateScoreRecord(client,provider,socRecType,reg,code,scoreRule,i,null,entity);

                        client.TotalScore = client.TotalScore == null ? record.Score : client.TotalScore + record.Score;

                        entity.SaveChanges();
                    }

                }
                client=entity.Sale_Client.FirstOrDefault(p=>p.Id==client.ParentId);
            }

        }

        public static Sale_ActiveCode CreateActiveCode(EditionType edition, int period, int regPeriod)
        {
            Sale_ActiveCode ac = new Sale_ActiveCode();

            ac.Edition = (int)edition;
            ac.Code = CreateCode();
            ac.IsRenewal = false;
            ac.CreateTime = DateTimeUtil.ChinaStandardTime;
            ac.Period = period;
            ac.RegPeriod = regPeriod;
            ac.IsUsed = true;
            return ac;
        }

        private static string CreateCode()
        {
            Random r = new Random(GetRandomSeed());

            string s = null;

            for (int i = 0; i < SERIAL_MAX_LENGTH; i++)
            {
                int index = r.Next(1, Seeds.Count());
                s += Seeds[index];

                int i2 = i + 1;

                if (i2 % 5 == 0 && i2 != SERIAL_MAX_LENGTH)
                    s += "-";
            }

            return s;
        }

        private static int GetRandomSeed()
        {
            byte[] bytes = new byte[4];
            System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
            rng.GetBytes(bytes);
            return BitConverter.ToInt32(bytes, 0);
        }
    }
}